/**
 * Created by yazhou on 17/6/28.
 */

'use strict'

import { constants } from './constants'
import { Session } from './session'
import { extend } from './extend'
import * as loginLib from './login'
import { sign } from './sign'

let noop = function noop() {}

let buildAuthHeader = function buildAuthHeader(session) {
	var header = {}

	if (session && session.skey) {
		header[constants.WX_HEADER_SKEY] = session.skey
		header[constants.WX_HEADER_EXPIRE] = session.expire
		header[constants.WX_HEADER_SIGN] = session.sign
	}

	return header
}

/***
 * @class
 * 表示请求过程中发生的异常
 */
let RequestError = (function () {
	function RequestError(type, message) {
		Error.call(this, message)
		this.type = type
		this.message = message
	}

	RequestError.prototype = new Error()
	RequestError.prototype.constructor = RequestError

	return RequestError
})()

function request(options) {
    // console.log(options)
	if (typeof options !== 'object') {
		var message = '请求传参应为 object 类型，但实际传了 ' + (typeof options) + ' 类型'

		throw new RequestError(constants.ERR_INVALID_PARAMS, message)
	}

	var requireLogin = options.login
	var success = options.success || noop
	var fail = options.fail || noop
	var complete = options.complete || noop
	var originHeader = options.header || {}

	// 成功回调
	var callSuccess = function () {
		success.apply(null, arguments)
		complete.apply(null, arguments)
	}

	// 失败回调
	var callFail = function (error) {
		fail.call(null, error)
		complete.call(null, error)
	}

	// 是否已经进行过重试
	var hasRetried = false

	if (requireLogin) {
		doRequestWithLogin()
	} else {
		doRequest()
	}

	// 登录后再请求
	function doRequestWithLogin() {
		loginLib.login({success: doRequest, fail: callFail})
	}

	// 实际进行请求的方法
	function doRequest() {
		var authHeader = buildAuthHeader(Session.get())
		var userinfo = {}
		var header = extend({}, originHeader, authHeader)
		var verb = 'request'

		try {
			userinfo = wx.getStorageSync('userinfo') || {}
		} catch (e) {
			//
		}

		// 文件上传标识
		if (options.uploadFile == true) {
			verb = 'uploadFile'
			header[constants.WX_HEADER_NO_CHECK] = 1
		}

		if (! requireLogin && ! userinfo.mobile_phone) {
			header[constants.WX_HEADER_NO_CHECK] = 1
		}

		if (userinfo.uid) options.data.login_uid = userinfo.uid
    // if (userinfo.uid) options.data.login_uid = '34350310'
		if (userinfo.login_token) options.data.login_token = userinfo.login_token
		if (userinfo.openid) options.data.openid = userinfo.openid
		if (userinfo.unionid) options.data.unionid = userinfo.unionid

		// 参数签名逻辑
		sign(options)

		wx[verb](extend({}, options, {
			header: header,

			success: function (response) {
				if (verb == 'uploadFile') {
					if (response.statusCode == 200) {
						response.data = JSON.parse(response.data)
					} else {
						response.data = {}
					}
				}

				var data = response.data && response.data.original && response.data.original.data
					? response.data.original.data
					: {}

				// 如果响应的数据里面包含 SDK Magic ID，表示被服务端处理过，此时一定包含登录状态信息
				if (data[constants.WX_SESSION_MAGIC_ID] === 1) { // 用户登录成功
					// 存储后端返回的session
					// var userinfo = wx.getStorageSync('userinfo') || {}

					userinfo = extend(true, {}, userinfo, data)

					try {
						wx.setStorageSync('userinfo', userinfo)
					} catch (e) {
						//
					}
				} else if (data[constants.WX_SESSION_MAGIC_ID] === 0) { // 小程序登录状态已过期
					// 清除登录态
					Session.clear()

					// 如果是登录态无效，并且还没重试过，会尝试登录后刷新凭据重新请求
					if (! hasRetried && requireLogin) {
						hasRetried = true
						doRequestWithLogin()

						return
					}

					var message = '登录状态已过期'
					var error = new RequestError('A500', message)

					callFail(error)

					return
				} else if (response.statusCode !== 200 || (response.data && response.data.original && response.data.original.status !== 'success')) {
                    // wx.setClipboardData({
                    //   data: options.url,
                    // })
					var message = (response.data && response.data.original && response.data.original.msg) || '服务器发生错误'
					var error = new RequestError(response.statusCode, message)

					callFail(error)

					return
				}

				callSuccess.apply(null, arguments)
			},

			fail: callFail,
			complete: noop,
		}))
	}
}

export { RequestError, request }
